function onload() {
  console.log("document.onload()");

  function onOpened() {
    console.log("opened");
  };
  function onMessage(e) {
    var msg = e.data;
    console.log("message:" + msg);
    setTreeMessage(msg)
  };
  function onError(e) {
    console.log("onerror:" + e.description);
  };
  function onClose() {
    console.log("close");
  };

  var treeClosedRe = /Tree is close/i;
  var treeOpenedRe = /Tree is open/i;
  function setTreeMessage(msg) {
    var d = document.getElementById("tree-status");
    d.innerText = msg;
    d.classList.remove('loading');
    if (treeClosedRe.test(msg)) {
      d.classList.add('tree-closed');
      d.classList.remove('tree-open');
    } else if (treeOpenedRe.test(msg)) {
      d.classList.add('tree-open');
      d.classList.remove('tree-closed');
    }
  }

  var channel = new goog.appengine.Channel(yoloChannelToken);
  var socket = channel.open();
  socket.onopen = onOpened;
  socket.onmessage = onMessage;
  socket.onerror = onError;
  socket.onclose = onClose;
  console.log("Channel initialization done", yoloChannelToken);

  $.post('/ajax/tree_status', {}, setTreeMessage);

  console.log("onload done");
}

var yolo = yolo || {};

yolo.showAjaxError = function(jqxhr, textStatus, error) {
  var errorText = jqxhr.status + ': ';
  if (jqxhr.responseText) {
    errorText += jqxhr.responseText.split('\n')[0];
  } else {
    errorText += textStatus;
  }
  console.log('ERROR:' + errorText)
  $('#ajax-result-body').text(errorText);
  $('#ajax-result').removeClass('loading').addClass('error').delay(30000).fadeOut('slow');
};

yolo.postAjaxLink = function(url, data, reload) {
  if (data == null || typeof(data) == 'undefined') {
    data = {};
  }
  data.xsrf = yoloXsrfToken;
  $('#ajax-result-body').text('')
  $('#ajax-result').removeClass('hide').removeClass('warning').removeClass('error').addClass('loading').fadeIn('fast');
  $.ajax({
    type: "POST",
    url: url,
    data: data,
    success: function(msg) {
      $('#ajax-result-body').text(msg);
      $('#ajax-result').removeClass('loading').addClass('warning').delay(10000).fadeOut('slow');
      if (reload) {
        location.reload();
      }
    },
    error: yolo.showAjaxError
  });
}

yolo.escapeHTML = function(target) {
  var div = document.createElement('div');
  var text =  document.createTextNode('');
  div.appendChild(text);
  text.data = target;
  return div.innerHTML;
}

yolo.epochToLocalDate = function(epoch) {
  var d = new Date();
  d.setTime(Date.parse(epoch));
  return d.toLocaleString();
}

yolo.epochToHowLongAgo = function(epoch) {
  var d = new Date();
  var diff = Math.floor((d.getTime() - Date.parse(epoch)) / 1000);
  var plural = function(num) {
    return num >= 2 ? 's' : '';
  }
  if (diff > 60 * 60 * 24 * 30) {
    var m = Math.floor(diff / (60 * 60 * 24 * 30));
    return m + ' month' + plural(m) + ' ago'
  }
  if (diff > 60 * 60 * 24) {
    var d = Math.floor(diff / (60 * 60 * 24));
    return d + ' day' + plural(d) + ' ago'
  }
  if (diff > 60 * 60) {
    var h = Math.floor(diff / (60 * 60));
    return h + ' hour' + plural(h) + ' ago'
  }
  if (diff > 60) {
    var m = Math.floor(diff / 60);
    return m + ' minute' + plural(m) + ' ago'
  }
  return diff + ' sec' + plural(diff) + ' ago'
}

yolo.getEmailPrefix = function(email) {
  if (!email || email.length == 0) {
    return '';
  }
  return email.split('@')[0];
}

yolo.toggleExpandIssue = function(issue) {
  var expanded = $('#issue-details-' + issue).is(':visible');
  $('.issue-details').hide();
  $('.issue-file-detail').hide().empty();
  $('.issue-item').removeClass('expanded').addClass('non-expanded');
  if (!expanded) {
    $('#issue-item-' + issue).addClass('expanded').removeClass('non-expanded');
    $('#issue-details-' + issue).fadeIn('fast');
  }
}

yolo.loadIssue = function(index, issue) {
  if (issue == '')
    return;
  if (yolo.lastPost)
    yolo.lastPost.abort();
  var expanded = $('#activity-detail-' + index).is(':visible');
  $('.activity-detail').hide().empty();
  $('.issue-file-detail').hide().empty();
  $('.activity').removeClass('expanded').addClass('non-expanded');
  if (expanded)
    return;
  $('#activity-detail-' + index).empty().removeClass('hide').addClass('loading').fadeIn('fast');
  yolo.lastPost = $.post(
      '/ajax/get_issue',
      {xsrf:yoloXsrfToken, issue:issue},
      function(data) {
        console.log("loadIssue: got:", data)
        yoloXsrfToken = data.XSRFToken;
        $('#activity-' + index).removeClass('non-expanded').addClass('expanded');
        $('#issueTemplate').tmpl(data.Data).appendTo('#activity-detail-' + index);
        $('#activity-detail-' + index).removeClass('loading');
      });
}

// TODO: Merge this with yolo.loadIssue()
yolo.loadIssueDetail = function(site, issue) {
  if (issue == '')
    return;
  if (yolo.lastPost)
    yolo.lastPost.abort();
  var expanded = $('#issue-detail-' + issue).is(':visible');
  $('.issue-detail').hide().empty();
  $('.issue-file-detail').hide().empty();
  $('.issue-item').removeClass('expanded').addClass('non-expanded');
  if (expanded)
    return;
  $('#issue-detail-' + issue).empty().removeClass('hide').addClass('loading').fadeIn('fast');
  yolo.lastPost = $.post(
      '/ajax/get_issue',
      {xsrf:yoloXsrfToken, issue:site + '/' + issue},
      function(data) {
        console.log("loadIssue: got:", data)
        yoloXsrfToken = data.XSRFToken;
        $('#issue-item-' + issue).removeClass('non-expanded').addClass('expanded');
        $('#issueTemplate').tmpl(data.Data).appendTo('#issue-detail-' + issue);
        $('#issue-detail-' + issue).removeClass('loading');
      });
}

yolo.stopPropagation = function(e) {
  var ev = e || window.event;
  if (ev.cancelBubble)
    ev.cancelBubble = true;
  else
    ev.stopPropagation();
}

yolo.loadFile = function(e, id, detailClass, path) {
  yolo.stopPropagation(e);
  if (yolo.lastPost)
    yolo.lastPost.abort();

  $(detailClass).empty().hide();
  $(id).addClass('loading').removeClass('hide').show();
  yolo.lastPost = $.post(
      '/ajax/get_file',
      {xsrf:yoloXsrfToken, path:path},
      function(data) {
        console.log("loadFile: got:", data)
        yoloXsrfToken = data.XSRFToken;
        data.Data.Path = path;
        data.Data.Div = id;
        yolo.decorateWithHeatColor(data.Data.ActiveUsers);
        $(id).removeClass('loading').empty();
        $('#fileTemplate').tmpl(data.Data).appendTo(id);
        $(id).text(data);
      });
}

yolo.closeDiv = function(e, id) {
  yolo.stopPropagation(e);
  $(id).hide().empty();
}

yolo.breakLine = function(text) {
  var lines = yolo.escapeHTML(text).split('\n');
  var compact = [];
  for (var i = 0; i < lines.length; i++) {
    var trimmed = lines[i].trim();
    if (trimmed.length > 0) {
      compact.push(trimmed);
    }
  }
  return compact.join('<br />');
}

yolo.showHeatGraph = function(id, canvas, commits) {
  $(id).removeClass('hide').show();
  yolo.drawHeatGraph(canvas, commits);
}

yolo.showHeatGraph = function(id, canvas, commits) {
  $(id).removeClass('hide').show();
  yolo.drawHeatGraph(canvas, commits);
}

yolo.getHeatColor = function(value, max, alpha) {
  cmap = yolo.getHeatColormap();
  var v = Math.floor(255 * (value / max));
  var r = cmap[v*4];
  var g = cmap[v*4+1];
  var b = cmap[v*4+2];
  return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
}

yolo.decorateWithHeatColor = function(countMap) {
  if (!countMap)
      return;
  var max = countMap.length > 0 ? countMap[0].Count : 1;
  for (var i = 0; i < countMap.length; i++) {
    var item = countMap[i];
    item.color = yolo.getHeatColor(item.Count, max, 0.65);
  }
}
